package com.example.walkingtour;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import com.example.walkingtour.data.*;
import android.content.Context;
import android.database.Cursor;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.content.CursorLoader;

/**
 * Private class to hold static variables and methods that are needed across the
 * WalkingTour Application
 * 
 * @author Tony
 * 
 */
public final class WalkingTourHelper {
	public static final int ACTION_TAKE_VIDEO = 1, ACTION_TAKE_AUDIO = 2,
			ACTION_TAKE_PIC = 3;
	public static final String[] FILE_EXTENSION = { "", ".3gp", ".mp3", ".jpg" };
	public static final String[] COLUMN_NAMES = new String[] {
			WTDatabase.KEY_ROWID, WTDatabase.COL_FILE, WTDatabase.COL_GPS_LAT,
			WTDatabase.COL_GPS_LONG, WTDatabase.COL_PATH,
			WTDatabase.COL_RECORDING_TYPE, WTDatabase.COL_TIME };

	// private default constructor prevents instantiation
	private WalkingTourHelper() {
	}

	/**
	 * Finds the Action identifier based on a file's path.
	 * 
	 * @param absolutePath
	 *            String containing full path of the file to be evaluated
	 * @return
	 */
	public static int getActionByPath(String absolutePath) {
		int action = 0;
		int found = absolutePath
				.lastIndexOf(WalkingTourHelper.FILE_EXTENSION[WalkingTourHelper.ACTION_TAKE_VIDEO]);
		if (found != -1)
			action = WalkingTourHelper.ACTION_TAKE_VIDEO;
		found = absolutePath
				.lastIndexOf(WalkingTourHelper.FILE_EXTENSION[WalkingTourHelper.ACTION_TAKE_AUDIO]);
		if (found != -1)
			action = WalkingTourHelper.ACTION_TAKE_AUDIO;
		found = absolutePath
				.lastIndexOf(WalkingTourHelper.FILE_EXTENSION[WalkingTourHelper.ACTION_TAKE_PIC]);
		if (found != -1)
			action = WalkingTourHelper.ACTION_TAKE_PIC;
		return action;
	}

	/**
	 * Queries DB with row's id to determine the File
	 * 
	 * @param id
	 *            row id
	 * @param context
	 *            context, used for resolving URI and querying database
	 * @return returns a File object with a path that corresponds to the row id
	 */
	public static File getFileById(long id, Context context) {
		Uri itemUri = Uri.withAppendedPath(WTProvider.CONTENT_URI,
				String.valueOf(id));
		Cursor csr = context.getContentResolver().query(itemUri, COLUMN_NAMES,
				WTDatabase.KEY_ROWID + "=" + id, null, null);

		String file = "";
		String path = "";
		try {
			csr.moveToFirst();
			file = csr.getString(csr.getColumnIndex(WTDatabase.COL_FILE));
			path = csr.getString(csr.getColumnIndex(WTDatabase.COL_PATH));
			csr.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new File(path, file);
	}

	/**
	 * Helper method to convert a Uri that has scheme "content" to a Uri that
	 * has scheme "file"
	 * 
	 * @param uri
	 *            Uri that has a "content" scheme
	 * @param context
	 *            Context, used to resolve the content Uri
	 * @return Returns a Uri, with "file" scheme on success If uri is not a
	 *         content Uri, returns original Uri
	 */
	public static Uri convertContentUriToFileUri(Uri uri, Context context) {
		if (uri == null || context == null)
			return null;
		if (uri.getScheme().equals("content")) {
			/*
			 * Found this code on stackoverflow. this is to resolve the issue
			 * where files are not created the way as described when specifying
			 * intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri)
			 * http://stackoverflow
			 * .com/questions/3401579/get-filename-and-path-from
			 * -uri-from-mediastore
			 */
			String[] proj = { MediaStore.Images.Media.DATA };
			CursorLoader loader = new CursorLoader(context, uri, proj, null,
					null, null);
			Cursor cursor = loader.loadInBackground();
			int column_index = cursor
					.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
			cursor.moveToFirst();
			String temppath = cursor.getString(column_index);
			temppath.toString();
			uri = Uri.fromFile(new File(temppath));
		}
		return uri;
	}

	/**
	 * Method renames a file, even across storage devices Purpose: File class's
	 * rename method doesn't work across devices, this method will work across
	 * storage devices
	 * 
	 * @param oldName
	 *            File that will be moved/renamed FROM
	 * @param newName
	 *            File that will be moved/rename TO
	 * @return returns true if transfer is successfull, and new file is readable
	 *         returns false otherwise
	 * @throws FileNotFoundException
	 *             carried forward from File.delete()
	 * @throws IOException
	 *             carried forward from FileInputStream methods
	 */
	public static boolean renameFile(File oldName, File newName)
			throws FileNotFoundException, IOException {
		if (!newName.getAbsolutePath().equals(oldName.getAbsolutePath())) {
			newName.createNewFile();
			FileChannel input = (new FileInputStream(oldName)).getChannel();
			FileChannel output = (new FileOutputStream(newName)).getChannel();
			try {
				input.transferTo(0, input.size(), output);
			} finally {
				if (input != null)
					input.close();
				if (output != null)
					output.close();
			}
			oldName.delete();
			if (newName.exists() && newName.canRead())
				return true;
		}
		return false;
	}

	/**
	 * Method retrieves the Length information from a File Uri
	 * 
	 * @param clipUri
	 *            file Uri for the recording
	 * @return returns the duration in "mm:ss" format
	 */
	public static String getLengthOfRecording(Uri clipUri, Context context) {
		String s;
		long duration = 0;
		SimpleDateFormat df = new SimpleDateFormat("mm:ss");
		MediaMetadataRetriever meta = new MediaMetadataRetriever();

		meta.setDataSource(context, clipUri);
		s = meta.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
		duration = Long.parseLong(s);
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTimeInMillis(duration);
		meta.release();

		s = df.format(gc.getTime());
		return s;
	}
}
